﻿using System;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using AForge.Imaging;
using AForge.Imaging.Filters;
using FPPrinter.Models.Doc;
using Newtonsoft.Json;

namespace FPPrinter.utiles
{
    public static class Utils
    {
        
        
        
        public static void   UseUIThread(this object o, Action func )
        {
            Application.Current.Dispatcher.Invoke(func);
             
        }        
 
        
        // public static Action  Debounce (Action  action, int milliseconds = 300)
        // {
        //     CancellationTokenSource cancellationTokenSource = null;
        //
        //     return arg =>
        //     {
        //         cancellationTokenSource?.Cancel();
        //         cancellationTokenSource = new CancellationTokenSource();
        //
        //         Task.Delay(milliseconds, cancellationTokenSource.Token)
        //             .ContinueWith(t =>
        //             {
        //                 if (!t.IsCanceled)
        //                 {
        //                     action(arg);
        //                 }
        //             }, TaskScheduler.FromCurrentSynchronizationContext());
        //     };
        // }
        
        

        public static Action<T>  Debounce<T>(this object o, Action<T> action, int milliseconds = 300)
        {
              CancellationTokenSource cancellationTokenSource = null;

            return arg =>
            {
                cancellationTokenSource?.Cancel();
                cancellationTokenSource = new CancellationTokenSource();
        
                Task.Delay(milliseconds, cancellationTokenSource.Token)
                    .ContinueWith(t =>
                    {
                        if (!t.IsCanceled)
                        {
                            action(arg);
                        }
                    }, TaskScheduler.FromCurrentSynchronizationContext());
            };
        }
        
       //  
       // static private readonly Action<string> _debouncedAction;
       //
       //  public static void  ExampleUsage()
       //  {
       //      // Wrap the method you want to debounce
       //      _debouncedAction = Debounce<string>(ExecuteAction, 300);
       //  }
       //
       //  public static void CallFunction(string input)
       //  {
       //      // Call this method rapidly; only the last call will be invoked after the specified delay
       //      _debouncedAction(input);
       //  }
       //
       //  private static void ExecuteAction(string data)
       //  {
       //      // This will only be invoked for the last call
       //      Console.WriteLine($"Executing action with data: {data}");
       //  }
       //  
        
        
        
        public static void MakeSurePathIsAvaliable(this string filePath  )
        {
            var p = Path.GetDirectoryName(filePath);
            // string filePath = "C:\\path\\to\\file.txt";
            if (!Directory.Exists(p))
            {
                Directory.CreateDirectory( p);
            }
        }

        public static void Echo(this object o, bool formated = true)
        {
            Console.WriteLine(o.ToJson(formated));
        }

        public static string ToJson(this object o, bool indented = true)
        {
            // Serialize the object to JSON
            string json = JsonConvert.SerializeObject(o, indented ? Formatting.Indented : Formatting.None);

            return json;
        }
        public static T ToObject<T>(this string o, bool indented = true)
        {
            // Serialize the object to JSON
            var  obj = JsonConvert.DeserializeObject<T>(o);
            
            
            return obj;
        }


        public static void Required(this string o, bool pre)
        {
            if (!pre) throw new Exception(o);
        }


        public static Rectangle DetectForContent(this IImage img)
        {
            var imgPath = img.Url;
            // Load the image containing the rectangle
            Bitmap image = new Bitmap(imgPath);

            // Convert the image to a compatible pixel format (e.g., 8bpp grayscale)
            Bitmap compatibleImage = Grayscale.CommonAlgorithms.BT709.Apply(image);

            // Apply edge detection filter
            SobelEdgeDetector edgeDetector = new SobelEdgeDetector();
            Bitmap edgesImage = edgeDetector.Apply(compatibleImage);

            // Apply blob counter to find rectangles
            BlobCounter blobCounter = new BlobCounter();
            blobCounter.ProcessImage(edgesImage);
            Blob[] blobs = blobCounter.GetObjectsInformation();

            if (blobs.Length < 1) throw new Exception("no blobs found");

            var rr = blobs[0].Rectangle;
            foreach (Blob blob in blobs)
            {
                // Get the rectangle dimensions
                Rectangle rectangle = blob.Rectangle;
                rr = MergeRectangles(rr, rectangle);
            }

            return rr;

            Rectangle MergeRectangles(Rectangle rect1, Rectangle rect2)
            {
                int x1 = Math.Min(rect1.X, rect2.X);
                int y1 = Math.Min(rect1.Y, rect2.Y);
                int x2 = Math.Max(rect1.Right, rect2.Right);
                int y2 = Math.Max(rect1.Bottom, rect2.Bottom);

                return new Rectangle(x1, y1, x2 - x1, y2 - y1);
            }
        }
    }
}